package com.mdd.front.service.region.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mdd.common.dto.RegionDto;
import com.mdd.common.dto.result.RegionResultDto;
import com.mdd.common.entity.region.DevRegion;
import com.mdd.common.entity.setting.DictData;
import com.mdd.common.entity.setting.DictType;
import com.mdd.common.enums.RegionLevelEnum;
import com.mdd.common.mapper.region.DevRegionMapper;
import com.mdd.common.mapper.setting.DictDataMapper;
import com.mdd.common.mapper.setting.DictTypeMapper;
import com.mdd.common.utils.PinyinUtil;
import com.mdd.front.service.region.IDevRegionService;
import com.mdd.front.vo.region.DevRegionFirstCharListVo;
import com.mdd.front.vo.region.DevRegionListVo;
import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 地区实现类
 */
@Service
public class DevRegionServiceImpl extends ServiceImpl<DevRegionMapper, DevRegion> implements IDevRegionService {

    @Resource
    DevRegionMapper devRegionMapper;

    private static Map<Long, String> regionMap;
    private static Map<String, Long> regionNameMap;
    private static List<DevRegionFirstCharListVo> charList;

    @Resource
    private DictDataMapper dictDataMapper;

    @Override
    public List<DevRegionListVo> province(int regionLevel) {
        return this.commonList(regionLevel, null);
    }

    @Override
    public List<DevRegionListVo> city(Long provinceId, int regionLevel) {
        return this.commonList(regionLevel, provinceId);
    }

    @Override
    public List<DevRegionListVo> district(Long cityId, int regionLevel) {
        return this.commonList(regionLevel, cityId);
    }

    private List<DevRegionListVo> commonList(Integer regionLevel, Long parentId) {
        List<DevRegionListVo> targetList = new ArrayList<>();
        RegionDto dto = new RegionDto();
        dto.setLevel(regionLevel);
        dto.setParentId(parentId);
        List<RegionResultDto> list = devRegionMapper.list(dto);
        for (RegionResultDto resultDto : list) {
            DevRegionListVo devRegion = new DevRegionListVo();
            BeanUtils.copyProperties(resultDto, devRegion);
            targetList.add(devRegion);
        }
        return targetList;
    }

    @Override
    public List<DevRegionListVo> tree(Long parentId, Integer regionLevel) {
        List<DevRegionListVo> list = this.commonList(regionLevel, parentId);
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        regionLevel = (regionLevel == null ? regionLevel = RegionLevelEnum.PROVINCE.getCode() : regionLevel);
        return this.buildTree(list, parentId, regionLevel);
    }

    private List<DevRegionListVo> buildTree(List<DevRegionListVo> allRegion, Long pid, int regionLeve) {
        List<DevRegionListVo> regionTreeList = new ArrayList<>();
        //获取省
        if (regionLeve == RegionLevelEnum.PROVINCE.getCode()) {
            List<DevRegionListVo> regionList = allRegion.stream().filter(region -> region.getLevel().equals(1)).collect(Collectors.toList());
            for (DevRegionListVo region : regionList) {
                DevRegionListVo regionTree = new DevRegionListVo();
                BeanUtils.copyProperties(region, regionTree);
                regionTreeList.add(regionTree);
            }
        } else if (regionLeve == RegionLevelEnum.CITY.getCode()) {
            //获取省市
            List<DevRegionListVo> regionList = allRegion.stream().filter(region -> region.getLevel().equals(1) || region.getLevel().equals(2)).collect(Collectors.toList());
            for (DevRegionListVo region : regionList) {
                if (Objects.equals(pid, region.getParentId())) {
                    DevRegionListVo regionTree = new DevRegionListVo();
                    BeanUtils.copyProperties(region, regionTree);
                    regionTree.setChildList(buildTree(allRegion, region.getId(), regionLeve));
                    regionTreeList.add(regionTree);
                }
            }
        } else {
            //获取省市区
            for (DevRegionListVo region : allRegion) {
                if (Objects.equals(pid, region.getParentId())) {
                    DevRegionListVo regionTree = new DevRegionListVo();
                    BeanUtils.copyProperties(region, regionTree);
                    regionTree.setChildList(buildTree(allRegion, region.getId(), regionLeve));
                    regionTreeList.add(regionTree);
                }
            }
        }
        return regionTreeList;
    }

    @Override
    public Map<Long, String> getRegionMap() {
        if (!org.springframework.util.CollectionUtils.isEmpty(regionMap)) {
            return regionMap;
        }
        List<DevRegion> list = super.list();
        if (CollectionUtils.isEmpty(list)) {
            return Maps.newHashMap();
        }
        regionMap = list.stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getName(), (a, b) -> b));
        return regionMap;
    }

    @Override
    public Map<String, Long> getRegionNameMap() {
        if (!org.springframework.util.CollectionUtils.isEmpty(regionMap)) {
            return regionNameMap;
        }
        List<DevRegion> list = super.list();
        if (CollectionUtils.isEmpty(list)) {
            return Maps.newHashMap();
        }
        regionNameMap = list.stream().collect(Collectors.toMap(item -> item.getName(), item -> item.getId(), (a, b) -> b));
        return regionNameMap;
    }

    @Override
    public List<DevRegionFirstCharListVo> charCity(int regionLeve) {
        if (CollectionUtils.isNotEmpty(charList)) {
            return charList;
        }
        LambdaQueryWrapper<DevRegion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DevRegion::getLevel, regionLeve);
        List<DevRegion> list = super.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return getDevRegionFirstCharListVos(list);
    }

    public List<DevRegionFirstCharListVo> getCity() {
        LambdaQueryWrapper<DictData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DictData::getTypeValue, "city");
        lambdaQueryWrapper.eq(DictData::getIsDelete, "0");
        List<DictData> dictData = dictDataMapper.selectList(lambdaQueryWrapper);
        List<DevRegion> list = new ArrayList<>();
        if(Objects.nonNull(dictData) && dictData.size() > 0) {
            // 根据字典表查询出服务的城市
            dictData.forEach(data -> {
                LambdaQueryWrapper<DevRegion> devRegionLambdaQueryWrapper = new LambdaQueryWrapper<>();
                devRegionLambdaQueryWrapper.eq(DevRegion::getName, data.getName());
                DevRegion devRegion = this.baseMapper.selectOne(devRegionLambdaQueryWrapper);
                list.add(devRegion);
            });
            return getDevRegionFirstCharListVos(list);
        }
        return null;
    }

    @NotNull
    private List<DevRegionFirstCharListVo> getDevRegionFirstCharListVos(List<DevRegion> list) {
        Map<String, List<DevRegionListVo>> map = Maps.newHashMap();
        for (DevRegion devRegion : list) {
            DevRegionListVo vo = new DevRegionListVo();
            BeanUtils.copyProperties(devRegion, vo);
            String firstChar = PinyinUtil.getPinYinFirstHeadChar(devRegion.getName());
            List<DevRegionListVo> devRegionListVos;
            if (map.containsKey(firstChar)) {
                devRegionListVos = map.get(firstChar);
            } else {
                devRegionListVos = Lists.newArrayList();
            }
            devRegionListVos.add(vo);
            map.put(firstChar, devRegionListVos);
        }
        List<DevRegionFirstCharListVo> targetList = Lists.newArrayList();
        for (Map.Entry<String, List<DevRegionListVo>> entry : map.entrySet()) {
            DevRegionFirstCharListVo vo = new DevRegionFirstCharListVo();
            vo.setFirstChar(entry.getKey());
            vo.setList(entry.getValue());
            targetList.add(vo);
        }
        Collections.sort(targetList);
        charList = targetList;
        return charList;
    }

    @Override
    public void delCache() {
        regionMap = null;
        charList = null;
        regionNameMap = null;
    }

    @PostConstruct
    public void cacheData() {
        List<DevRegion> list = devRegionMapper.selectAll();
        if (CollectionUtils.isNotEmpty(list)) {
            regionMap = list.stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getName(), (a, b) -> b));
            regionNameMap = list.stream().collect(Collectors.toMap(item -> item.getName(), item -> item.getId(), (a, b) -> b));
            List<DevRegion> filterList = list.stream().filter(item -> RegionLevelEnum.CITY.getCode() == item.getLevel()).collect(Collectors.toList());
            Map<String, List<DevRegionListVo>> map = Maps.newHashMap();
            for (DevRegion devRegion : filterList) {
                DevRegionListVo vo = new DevRegionListVo();
                BeanUtils.copyProperties(devRegion, vo);
                String firstChar = PinyinUtil.getPinYinFirstHeadChar(devRegion.getName());
                List<DevRegionListVo> devRegionListVos;
                if (map.containsKey(firstChar)) {
                    devRegionListVos = map.get(firstChar);
                } else {
                    devRegionListVos = Lists.newArrayList();
                }
                devRegionListVos.add(vo);
                map.put(firstChar, devRegionListVos);
            }
            List<DevRegionFirstCharListVo> targetList = Lists.newArrayList();
            for (Map.Entry<String, List<DevRegionListVo>> entry : map.entrySet()) {
                DevRegionFirstCharListVo vo = new DevRegionFirstCharListVo();
                vo.setFirstChar(entry.getKey());
                vo.setList(entry.getValue());
                targetList.add(vo);
            }
            Collections.sort(targetList);
            charList = targetList;
        }
    }
}
